package com.borened.common.core.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.borened.common.core.exception.BusinessException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.IntStream;

/**
 * @author jianghh
 */
@Component
public class SignUtil {
    @Value("${register.secret:efarm}")
    private String secret;

    public static String getMd5Sign(Map<String, Object> map, String secret) {
        return getMd5Sign(map, secret, null);
    }

    public static String getSha256Sign(Map<String, Object> map, String secret) {
        return getSha256Sign(map, secret, null);
    }

    public static String getMd5Sign(Map<String, Object> map, String secret, String timeStr) {
        timeStr = Convert.toStr(timeStr, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")));
        String pass = StrUtil.format("{}{}{}", "", secret, timeStr);
        return SecureUtil.md5(pass);
    }

    public static String getSha256Sign(Map<String, Object> map, String secret, String timeStr) {
        map = null;
        timeStr = Convert.toStr(timeStr, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")));
        String pass = StrUtil.format("{}{}{}", "", secret, timeStr);
        return SecureUtil.sha256(pass);
    }

    public <T> void accessSign(T params, String sign) {
        accessSign(params, sign, null);
    }

    public <T> void accessSign(T params, String sign, Integer maxWaitTime) {
        // 最大允许宽容时间
        maxWaitTime = Convert.toInt(maxWaitTime, 15);
//        if (!(params instanceof Map)) {
//            throw new BusinessException("当前只支持map类型传参");
//        }
        Map<String, Object> beanToMap;
        try {
            beanToMap = BeanUtil.beanToMap(params);
        } catch (Exception e) {
            throw new BusinessException("不支持的类型");
        }
        TreeMap<String, Object> map = MapUtil.sort(beanToMap);
        final boolean[] pass = {false};
        try {
            IntStream.range(-maxWaitTime, maxWaitTime).forEach(i -> {
                String time = LocalDateTimeUtil.format(LocalDateTime.now().plusMinutes(i), DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
                String md5Sign = getMd5Sign(map, secret, time);
                String sha256Sign = getSha256Sign(map, secret, time);
                pass[0] = StrUtil.equalsAny(sign, md5Sign, sha256Sign);
                Assert.isFalse(pass[0], RuntimeException::new);
            });
            throw new BusinessException();
        } catch (Exception e) {
            Assert.isFalse(!pass[0], () -> new BusinessException("密钥错误"));
        }
    }
}
